/*
 * Copyright 2016-2017 TVI Go Easy.
 * Created on 2017/6/16 17:47
 */
package com.gitee.mechanic.web.error;

import com.gitee.mechanic.core.exception.SuperException;
import com.gitee.mechanic.json.mapper.JsonMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.error.DefaultErrorAttributes;
import org.springframework.boot.web.servlet.error.ErrorAttributes;
import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.context.request.WebRequest;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.Map;

//import org.springframework.boot.autoconfigure.web.DefaultErrorAttributes;
//import org.springframework.boot.autoconfigure.web.ErrorAttributes;
//import org.springframework.boot.autoconfigure.web.ErrorController;

/**
 * 全局异常处理控制器
 *
 * @author mechanic
 * @version 0.0.1
 */
@Controller
public class ErrorPageController implements ErrorController {

    private final Logger logger = LoggerFactory.getLogger(getClass());

    private JsonMapper jsonMapper = new JsonMapper();

    @Value("${server.error.path}")
    private String path;

    private ErrorAttributes errorAttributes = new DefaultErrorAttributes(true);

    @RequestMapping(value = "${server.error.path}", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ResponseBody
    public ErrorMessage handle(HttpServletRequest request) {
        Map<String, Object> attributes = getErrorAttributes(request);

        String exception = (String) attributes.get("exception");
        String message = (String) attributes.get("message");
        String trace = (String) attributes.get("trace");
        int status = (int) attributes.get("status");
        String path = (String) attributes.get("path");
        String method = (String) attributes.get("method");
        Long timestamp = ((Date) attributes.get("timestamp")).toInstant().toEpochMilli();
        ErrorMessage result = new ErrorMessage(path, status, exception, message, trace, timestamp, method);

        logger.error("\n" + jsonMapper.toJson(result));

        return result;
    }

    private Map<String, Object> getErrorAttributes(HttpServletRequest request) {
        WebRequest webRequest = new ServletWebRequest(request);
        Map<String, Object> errorAttributes = this.errorAttributes.getErrorAttributes(webRequest, false);
        Throwable error = this.errorAttributes.getError(webRequest);
        if (error instanceof SuperException) {
            errorAttributes.put("status", ((SuperException) error).getHttpCode().getCode());
        }
        errorAttributes.put("method", request.getMethod());
        return errorAttributes;
    }

    private void logError(Map<String, Object> attributes, HttpServletRequest request) {
        attributes.put("from", request.getRemoteAddr());
        logger.error(jsonMapper.toJson(attributes));
    }

    @Override
    public String getErrorPath() {
        return this.path;
    }
}
